package model

import (
	"encoding/json"
	"fmt"
	"hft/global"
	"hft/tools/ws/single_ws/e"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

// 发送消息的类型
type SendMsg struct {
	Type     string   `json:"type"`
	Content  string   `json:"content"`
	MetaData MetaData `json:"meta_data,omitempty"` //扩展数据
}

// 内容扩展
type MetaData struct {
	MediaID string `json:"media_id,omitempty"` //媒体id
	LouPan  int    `json:"lou_pan,omitempty"`  //楼盘id
}

// 回复的消息
type ReplyMsg struct {
	From     string   `json:"from"`
	Code     int      `json:"code"`
	Type     string   `json:"type"`
	Content  string   `json:"content,omitempty"`
	MetaData MetaData `json:"meta_data,omitempty"`
}

// 用户
type Client struct {
	ID        string          //用户id
	SendID    string          //接受者的id
	Socket    *websocket.Conn //连接
	Send      chan []byte
	HeartTime int64  //当前心跳时间
	Page      string //当前页面
}

// 广播类 包括广播内容和源用户
type Broadcast struct {
	Client  *Client
	Message []byte
	Type    int
}

// 用户管理者
type ClientManager struct {
	Clients    map[string]*Client //用户表
	Broadcast  chan *Broadcast    //广播
	Reply      chan *Client
	Register   chan *Client
	Unregister chan *Client
	Mu         *sync.Mutex //异步同步锁
}

// Message 信息转JSON (包括：发送者、接收者、内容)
type Message struct {
	Sender    string `json:"sender,omitempty"`
	Recipient string `json:"recipient,omitempty"`
	Content   string `json:"content,omitempty"`
}

// 初始化一个管理者实例
var Manager = ClientManager{
	Clients:    make(map[string]*Client),
	Broadcast:  make(chan *Broadcast),
	Register:   make(chan *Client),
	Unregister: make(chan *Client),
	Mu:         new(sync.Mutex),
}

// 判断是否存在客户
func IsClientExist(list map[string]*Client, id string) bool {
	for k, _ := range list {
		if k == id {
			return true
		}
	}
	return false
}

// 用户的读操作
func (c *Client) Read() {
	defer func() { // 避免忘记关闭，所以要加上close
		Manager.Unregister <- c
		_ = c.Socket.Close()
	}()
	for {
		c.Socket.PongHandler()
		sendMsg := new(SendMsg)
		err := c.Socket.ReadJSON(&sendMsg) // 读取json格式，如果不是json格式，会报错
		if err != nil {
			log.Println("数据格式不正确", err)
			Manager.Unregister <- c
			_ = c.Socket.Close()
			break
		}
		// 每次有消息进来 ，都会刷新心跳时间
		c.HeartTime = time.Now().Unix()
		// 防止重复单聊
		var chatID = fmt.Sprintf("CHAT-%v_%v", c.Page, c.ID)
		var receiveID = fmt.Sprintf("CHAT-%v_%v", c.Page, c.SendID)
		r1, _ := global.OC_REDIS.Get(chatID).Result()
		r2, _ := global.OC_REDIS.Get(receiveID).Result()
		// 获取两个发送者的redis记录
		if r1 >= "3" && r2 == "" {
			// 如果对方不存在 则限聊
			replyMsg := ReplyMsg{Code: e.WebsocketLimit, Content: ""}
			msg, _ := json.Marshal(replyMsg)
			_ = c.Socket.WriteMessage(websocket.TextMessage, msg)
			continue
		} else {
			// 判断消息
			// 写消息
			data, _ := json.Marshal(sendMsg)
			Manager.Broadcast <- &Broadcast{Client: c, Message: data}
		}

	}
}

// 写操作
func (c *Client) Write() {
	defer func() {
		_ = c.Socket.Close()
	}()
	for {
		select {
		case message, ok := <-c.Send: //写入信息
			// 如果写入失败
			if !ok {
				_ = c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
			} else {
				// 结构
				var newMsg *ReplyMsg
				json.Unmarshal(message, &newMsg)
				var id = strings.Split(c.SendID, "-")[0]
				newMsg.From = id
				newMsg.Code = e.WebsocketSuccessMessage
				msg, _ := json.Marshal(newMsg)
				_ = c.Socket.WriteMessage(websocket.TextMessage, msg)
			}

		}
	}
}

func CreateId(page, uid, toUid string) string {
	return uid + "-" + toUid + "@" + page
}
